﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using MySql.Data.MySqlClient;

namespace Ocmf.Types
{
    public class Experiment : TreeView
    {
        public string ExperimentId { get; set; }
        public string FileName { get; private set; }
        public DateTime LastSaved { get; private set; }
        public long DatabaseId { get; private set; }
        public ScreenTemplate ScreenTemplate { get; set; }
        public int CardsPerTrial { get; set; }
        public List<string> Counters { get; set; }
        
        public Experiment()
        {
            DatabaseId = -1;
            ImageKey = "experiment";
            Counters = new List<string>();
        }

        public void Save()
        {
            Save(FileName);
        }

        public void Save(string path)
        {
            try
            {
                FileName = path;
                //create xml document and file declaration
                var xmlDocument = new XmlDocument();
                var xmlDeclaration = xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", "yes");
                xmlDocument.AppendChild(xmlDeclaration);

                //create the root element
                var experimentElement = xmlDocument.CreateElement("Experiment");

                //create, set and add the application version
                var versionAttribute = xmlDocument.CreateAttribute("OcmfVersion");
                versionAttribute.InnerText = Application.ProductVersion;
                experimentElement.Attributes.Append(versionAttribute);

                //set the name attribute to the user name of the experiment
                var experimentNameAttribute = xmlDocument.CreateAttribute("Text");
                experimentNameAttribute.InnerText = Text;
                experimentElement.Attributes.Append(experimentNameAttribute);

                //create, set and add the imagespertrial attribute
                var cardsPerTrialAttribute = xmlDocument.CreateAttribute("CardsPerTrial");
                cardsPerTrialAttribute.InnerText = CardsPerTrial.ToString();
                experimentElement.Attributes.Append(cardsPerTrialAttribute);

                //create,set and add the DatabaseId attribute
                var databaseIdAttribute = xmlDocument.CreateAttribute("DatabaseId");
                databaseIdAttribute.InnerText = DatabaseId.ToString();
                experimentElement.Attributes.Append(databaseIdAttribute);

                //create, set and add the lastsaved attribute
                var lastSavedAttribute = xmlDocument.CreateAttribute("LastSaved");
                lastSavedAttribute.InnerText = DateTime.Now.ToString();
                experimentElement.Attributes.Append(lastSavedAttribute);

                //create counters list
                var countersNode = xmlDocument.CreateElement("Counters");
                for (int i = 0; i < Counters.Count; i++)
                {
                    var counterNode = xmlDocument.CreateElement("Counter");
                    counterNode.InnerText = Counters[i];
                    countersNode.AppendChild(counterNode);
                }
                experimentElement.AppendChild(countersNode);

                //iterate over each trial in the experiment contents
                foreach (Action action in Nodes)
                    experimentElement.AppendChild(action.ToXml(xmlDocument));

                //append the root to the document
                xmlDocument.AppendChild(experimentElement);
                xmlDocument.Save(path);
            }
            catch (Exception)
            {
                MessageBox.Show("Could not save experiment file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        public void Open(string path)
        {
            //try
            //{
                //load xml document
                FileName = path;
                var xmlDocument = new XmlDocument();
                xmlDocument.Load(path);

                //assign attributes
                Text = xmlDocument.DocumentElement.Attributes["Text"].InnerText;
                CardsPerTrial = int.Parse(xmlDocument.DocumentElement.Attributes["CardsPerTrial"].InnerText);

                //iterate through each child node
                Nodes.Clear();

                var counterNode = xmlDocument.DocumentElement["Counters"]["Counter"];
                while (counterNode != null)
                {
                    Counters.Add(counterNode.InnerText);
                    counterNode = (XmlElement) counterNode.NextSibling;
                }

                var trialNodes = xmlDocument.DocumentElement["Trial"];
                while (trialNodes != null)
                {
                    var trial = new Trial();
                    trial.FromXml(trialNodes);
                    Nodes.Add(trial);
                    trial.Text = "[" + trial.Index + "] " + trial.Alias;
                    trialNodes = (XmlElement) trialNodes.NextSibling;
                }

                ExpandAll();

                foreach (Trial trial in Nodes)
                    trial.Alias = trial.Alias;
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show("Could not open experiment file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //}
        }

        public bool CheckSaveState()
        {
            if(FileName == null) return true;
            //save the current experiment

            var filePathCopy = (string)FileName.Clone();
            Save(Path.Combine(Application.StartupPath, "temp_cuurentexperiment.experiment"));
            FileName = filePathCopy;

            var originalExperimentBytes = File.ReadAllBytes(FileName);
            var currentExperimentBytes = File.ReadAllBytes(Path.Combine(Application.StartupPath, "temp_cuurentexperiment.experiment"));

            //first check size
            if (originalExperimentBytes.Length != currentExperimentBytes.Length) return false;

            //check byte-by-byte
            for (var i = 0; i < originalExperimentBytes.Length; i++)
                if (originalExperimentBytes[i] != currentExperimentBytes[i])
                    return false;

            return true;
        }

        public static Experiment LoadProperties(string path)
        {
            return new Experiment
                       {
                           FileName = Path.GetFileName(path),
                           LastSaved = File.GetLastWriteTime(path),
                       };
        }
    }
}
